์ฌ์ฉ์ ์ ์ ์์ธ ์ฒ๋ฆฌ๊ธฐ๋ก FastAPI ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ๋ง์คํฐํ์ธ์. ๋ ๋์ ์ฌ์ฉ์ ๊ฒฝํ์ ์ํด ์ ์์ ์ธ ์ค๋ฅ ์๋ต์ผ๋ก ๊ฐ๋ ฅํ API๋ฅผ ๊ตฌ์ถํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ฐ์ธ์. ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ ์ฑ๊ณผ ์ ์ง ๊ด๋ฆฌ์ฑ์ ํฅ์์ํค์ธ์.
Python FastAPI ์ค๋ฅ ์ฒ๋ฆฌ: ๊ฐ๋ ฅํ ์ฌ์ฉ์ ์ ์ ์์ธ ์ฒ๋ฆฌ๊ธฐ ๊ตฌ์ถ
์ค๋ฅ ์ฒ๋ฆฌ๋ ๊ฐ๋ ฅํ๊ณ ์์ ์ ์ธ API๋ฅผ ๊ตฌ์ถํ๋ ๋ฐ ์์ด ์ค์ํ ์ธก๋ฉด์ ๋๋ค. Python์ FastAPI์์๋ ์ฌ์ฉ์ ์ ์ ์์ธ ์ฒ๋ฆฌ๊ธฐ๋ฅผ ํ์ฉํ์ฌ ์ค๋ฅ๋ฅผ ์ ์์ ์ผ๋ก ๊ด๋ฆฌํ๊ณ ํด๋ผ์ด์ธํธ์ ์ ์ฉํ ์๋ต์ ์ ๊ณตํ ์ ์์ต๋๋ค. ์ด ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ์์๋ FastAPI์์ ์ฌ์ฉ์ ์ ์ ์์ธ ์ฒ๋ฆฌ๊ธฐ๋ฅผ ๋ง๋๋ ๊ณผ์ ์ ์๋ดํ์ฌ ๋์ฑ ํ๋ ฅ์ ์ด๊ณ ์ฌ์ฉ์ ์นํ์ ์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์๋๋ก ํฉ๋๋ค.
์ฌ์ฉ์ ์ ์ ์์ธ ์ฒ๋ฆฌ๊ธฐ๊ฐ ํ์ํ ์ด์ ?
FastAPI๋ ์์ธ ์ฒ๋ฆฌ๋ฅผ ์ํ ๊ธฐ๋ณธ ์ ๊ณต ์ง์์ ์ ๊ณตํฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ธฐ๋ณธ ์ค๋ฅ ์๋ต์๋ง ์์กดํ๋ฉด ํด๋ผ์ด์ธํธ๋ ๋ชจํธํ๊ฑฐ๋ ๋์์ด ๋์ง ์๋ ์ ๋ณด๋ง ์ป์ ์ ์์ต๋๋ค. ์ฌ์ฉ์ ์ ์ ์์ธ ์ฒ๋ฆฌ๊ธฐ๋ ๋ค์๊ณผ ๊ฐ์ ์ฌ๋ฌ ๊ฐ์ง ์ด์ ์ ์ ๊ณตํฉ๋๋ค.
- ํฅ์๋ ์ฌ์ฉ์ ๊ฒฝํ: ํน์ ์ค๋ฅ ์๋๋ฆฌ์ค์ ๋ง๊ฒ ๋ช ํํ๊ณ ์ ์ฉํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ์ค์ ์ง์ค์ ์ค๋ฅ ๊ด๋ฆฌ: ์ค๋ฅ ์ฒ๋ฆฌ ๋ก์ง์ ํ ๊ณณ์ ํตํฉํ์ฌ ์ฝ๋ ์ ์ง ๊ด๋ฆฌ์ฑ์ ๋์ ๋๋ค.
- ์ผ๊ด๋ ์ค๋ฅ ์๋ต: ์ค๋ฅ ์๋ต์ด ์ผ๊ด๋ ํ์์ ๋ฐ๋ฅด๋๋ก ํ์ฌ API ์ฌ์ฉ์ฑ์ ํฅ์์ํต๋๋ค.
- ๊ฐํ๋ ๋ณด์: ์ค๋ฅ ๋ฉ์์ง์ ๋ฏผ๊ฐํ ์ ๋ณด๊ฐ ๋ ธ์ถ๋์ง ์๋๋ก ํฉ๋๋ค.
- ์ฌ์ฉ์ ์ ์ ๋ก๊น : ๋๋ฒ๊น ๋ฐ ๋ชจ๋ํฐ๋ง์ ์ํด ์์ธํ ์ค๋ฅ ์ ๋ณด๋ฅผ ๊ธฐ๋กํฉ๋๋ค.
FastAPI์ ์์ธ ์ฒ๋ฆฌ ์ดํด
FastAPI๋ Python์ ๊ธฐ๋ณธ ์ ๊ณต ์์ธ ์ฒ๋ฆฌ ๋ฉ์ปค๋์ฆ๊ณผ ์์ฒด ์ข ์์ฑ ์ฃผ์ ์์คํ ์ ๊ฒฐํฉํ์ฌ ์ค๋ฅ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. ๋ผ์ฐํธ ๋๋ ์ข ์์ฑ ๋ด์์ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด FastAPI๋ ์ด๋ฅผ ์ฒ๋ฆฌํ ์ ์ ํ ์์ธ ์ฒ๋ฆฌ๊ธฐ๋ฅผ ์ฐพ์ต๋๋ค.
์์ธ ์ฒ๋ฆฌ๊ธฐ๋ @app.exception_handler()๋ก ๋ฐ์ฝ๋ ์ดํธ๋ ํจ์์ด๋ฉฐ, ์์ธ ์ ํ๊ณผ ์์ฒญ ๊ฐ์ฒด์ ๋ ๊ฐ์ง ์ธ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ฒ๋ฆฌ๊ธฐ๋ ์ ์ ํ HTTP ์๋ต์ ๋ฐํํ ์ฑ
์์ด ์์ต๋๋ค.
์ฌ์ฉ์ ์ ์ ์์ธ ๋ง๋ค๊ธฐ
์ฌ์ฉ์ ์ ์ ์์ธ ์ฒ๋ฆฌ๊ธฐ๋ฅผ ์ ์ํ๊ธฐ ์ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ํน์ ์ค๋ฅ ์กฐ๊ฑด์ ๋ํ๋ด๋ ์ฌ์ฉ์ ์ ์ ์์ธ ํด๋์ค๋ฅผ ๋ง๋๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋ ๊ฐ๋ ์ฑ์ด ํฅ์๋๊ณ ๋ค์ํ ์ ํ์ ์ค๋ฅ๋ฅผ ๋ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ์ ์ ์๊ฑฐ๋ API๋ฅผ ๊ตฌ์ถํ๊ณ ์ ํ ์ฌ๊ณ ๊ฐ ์๋ ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํด์ผ ํ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. OutOfStockError๋ผ๋ ์ฌ์ฉ์ ์ ์ ์์ธ ํด๋์ค๋ฅผ ์ ์ํ ์ ์์ต๋๋ค.
class OutOfStockError(Exception):
def __init__(self, product_id: int):
self.product_id = product_id
self.message = f"Product with ID {product_id} is out of stock."
์ด ์ฌ์ฉ์ ์ ์ ์์ธ ํด๋์ค๋ ๊ธฐ๋ณธ Exception ํด๋์ค์์ ์์๋๊ณ product_id ์์ฑ๊ณผ ์ฌ์ฉ์ ์ ์ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํฌํจํฉ๋๋ค.
์ฌ์ฉ์ ์ ์ ์์ธ ์ฒ๋ฆฌ๊ธฐ ๊ตฌํ
์ด์ OutOfStockError์ ๋ํ ์ฌ์ฉ์ ์ ์ ์์ธ ์ฒ๋ฆฌ๊ธฐ๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. ์ด ์ฒ๋ฆฌ๊ธฐ๋ ์์ธ๋ฅผ catchํ๊ณ ์ค๋ฅ ๋ฉ์์ง๊ฐ ํฌํจ๋ JSON ๋ณธ๋ฌธ๊ณผ ํจ๊ป HTTP 400 (์๋ชป๋ ์์ฒญ) ์๋ต์ ๋ฐํํฉ๋๋ค.
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse
app = FastAPI()
class OutOfStockError(Exception):
def __init__(self, product_id: int):
self.product_id = product_id
self.message = f"Product with ID {product_id} is out of stock."
@app.exception_handler(OutOfStockError)
async def out_of_stock_exception_handler(request: Request, exc: OutOfStockError):
return JSONResponse(
status_code=400,
content={"message": exc.message},
)
@app.get("/products/{product_id}")
async def get_product(product_id: int):
# Simulate checking product stock
if product_id == 123:
raise OutOfStockError(product_id=product_id)
return {"product_id": product_id, "name": "Example Product", "price": 29.99}
์ด ์์ ์์ @app.exception_handler(OutOfStockError) ๋ฐ์ฝ๋ ์ดํฐ๋ out_of_stock_exception_handler ํจ์๋ฅผ ๋ฑ๋กํ์ฌ OutOfStockError ์์ธ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. OutOfStockError๊ฐ get_product ๋ผ์ฐํธ์์ ๋ฐ์ํ๋ฉด ์์ธ ์ฒ๋ฆฌ๊ธฐ๊ฐ ํธ์ถ๋ฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ฒ๋ฆฌ๊ธฐ๋ ์ํ ์ฝ๋๊ฐ 400์ด๊ณ ์ค๋ฅ ๋ฉ์์ง๊ฐ ํฌํจ๋ JSON ๋ณธ๋ฌธ์ด ์๋ JSONResponse๋ฅผ ๋ฐํํฉ๋๋ค.
์ฌ๋ฌ ์์ธ ์ ํ ์ฒ๋ฆฌ
์ฌ๋ฌ ์์ธ ์ฒ๋ฆฌ๊ธฐ๋ฅผ ์ ์ํ์ฌ ๋ค์ํ ์ ํ์ ์์ธ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ฌ์ฉ์ ์
๋ ฅ์ ๊ตฌ๋ฌธ ๋ถ์ํ ๋ ๋ฐ์ํ๋ ValueError ์์ธ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
@app.exception_handler(ValueError)
async def value_error_exception_handler(request: Request, exc: ValueError):
return JSONResponse(
status_code=400,
content={"message": str(exc)},
)
@app.get("/items/{item_id}")
async def get_item(item_id: int):
# Simulate invalid item_id
if item_id < 0:
raise ValueError("Item ID must be a positive integer.")
return {"item_id": item_id, "name": "Example Item"}
์ด ์์ ์์ value_error_exception_handler ํจ์๋ ValueError ์์ธ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ์์ธ ๊ฐ์ฒด์์ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ถ์ถํ์ฌ JSON ์๋ต์ผ๋ก ๋ฐํํฉ๋๋ค.
HTTPException ์ฌ์ฉ
FastAPI๋ HTTP ๊ด๋ จ ์ค๋ฅ๋ฅผ ๋ฐ์์ํค๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ ๊ธฐ๋ณธ ์ ๊ณต ์์ธ ํด๋์ค์ธ HTTPException์ ์ ๊ณตํฉ๋๋ค. ์ด๋ ๋ฌด๋จ ์ก์ธ์ค ๋๋ ๋ฆฌ์์ค๋ฅผ ์ฐพ์ ์ ์์๊ณผ ๊ฐ์ ์ผ๋ฐ์ ์ธ ์ค๋ฅ ์๋๋ฆฌ์ค๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ์ ์ฉํ ์ ์์ต๋๋ค.
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/users/{user_id}")
async def get_user(user_id: int):
# Simulate user not found
if user_id == 999:
raise HTTPException(status_code=404, detail="User not found")
return {"user_id": user_id, "name": "Example User"}
์ด ์์ ์์ HTTPException์ ์ํ ์ฝ๋ 404 (์ฐพ์ ์ ์์) ๋ฐ ์ธ๋ถ ๋ฉ์์ง์ ํจ๊ป ๋ฐ์ํฉ๋๋ค. FastAPI๋ HTTPException ์์ธ๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌํ๊ณ ์ง์ ๋ ์ํ ์ฝ๋ ๋ฐ ์ธ๋ถ ๋ฉ์์ง์ ํจ๊ป JSON ์๋ต์ ๋ฐํํฉ๋๋ค.
์ ์ญ ์์ธ ์ฒ๋ฆฌ๊ธฐ
์ฒ๋ฆฌ๋์ง ์์ ๋ชจ๋ ์์ธ๋ฅผ catchํ๋ ์ ์ญ ์์ธ ์ฒ๋ฆฌ๊ธฐ๋ฅผ ์ ์ํ ์๋ ์์ต๋๋ค. ์ด๋ ์ค๋ฅ๋ฅผ ๊ธฐ๋กํ๊ฑฐ๋ ํด๋ผ์ด์ธํธ์ ์ผ๋ฐ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๋ฐํํ๋ ๋ฐ ์ ์ฉํ ์ ์์ต๋๋ค.
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import logging
app = FastAPI()
logger = logging.getLogger(__name__)
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
logger.exception(f"Unhandled exception: {exc}")
return JSONResponse(
status_code=500,
content={"message": "Internal server error"},
)
@app.get("/error")
async def trigger_error():
raise ValueError("This is a test error.")
์ด ์์ ์์ global_exception_handler ํจ์๋ ๋ค๋ฅธ ์์ธ ์ฒ๋ฆฌ๊ธฐ์์ ์ฒ๋ฆฌ๋์ง ์๋ ๋ชจ๋ ์์ธ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ์ค๋ฅ๋ฅผ ๊ธฐ๋กํ๊ณ ์ผ๋ฐ ์ค๋ฅ ๋ฉ์์ง์ ํจ๊ป 500 (๋ด๋ถ ์๋ฒ ์ค๋ฅ) ์๋ต์ ๋ฐํํฉ๋๋ค.
์์ธ ์ฒ๋ฆฌ๋ฅผ ์ํ ๋ฏธ๋ค์จ์ด ์ฌ์ฉ
์์ธ ์ฒ๋ฆฌ์ ๋ํ ๋ ๋ค๋ฅธ ์ ๊ทผ ๋ฐฉ์์ ๋ฏธ๋ค์จ์ด๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ๋ฏธ๋ค์จ์ด ํจ์๋ ๊ฐ ์์ฒญ ์ ํ์ ์คํ๋๋ฏ๋ก ๋ ๋์ ์์ค์์ ์์ธ๋ฅผ ๊ฐ๋ก์ฑ๊ณ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ์ด๋ ์์ฒญ ๋ฐ ์๋ต ๋ก๊น ๋๋ ์ฌ์ฉ์ ์ง์ ์ธ์ฆ ๋๋ ๊ถํ ๋ถ์ฌ ๋ก์ง ๊ตฌํ๊ณผ ๊ฐ์ ์์ ์ ์ ์ฉํ ์ ์์ต๋๋ค.
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import logging
app = FastAPI()
logger = logging.getLogger(__name__)
@app.middleware("http")
async def exception_middleware(request: Request, call_next):
try:
response = await call_next(request)
except Exception as exc:
logger.exception(f"Unhandled exception: {exc}")
return JSONResponse(
status_code=500,
content={"message": "Internal server error"},
)
return response
@app.get("/error")
async def trigger_error():
raise ValueError("This is a test error.")
์ด ์์ ์์ exception_middleware ํจ์๋ ์์ฒญ ์ฒ๋ฆฌ ๋ก์ง์ try...except ๋ธ๋ก์ผ๋ก ๋ํํฉ๋๋ค. ์์ฒญ ์ฒ๋ฆฌ ์ค์ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ๋ฏธ๋ค์จ์ด๊ฐ ์ค๋ฅ๋ฅผ ๊ธฐ๋กํ๊ณ 500 (๋ด๋ถ ์๋ฒ ์ค๋ฅ) ์๋ต์ ๋ฐํํฉ๋๋ค.
์: ๊ตญ์ ํ (i18n) ๋ฐ ์ค๋ฅ ๋ฉ์์ง
๊ธ๋ก๋ฒ ๋์์ ์ํ API๋ฅผ ๊ตฌ์ถํ ๋๋ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๊ตญ์ ํํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ฌ๊ธฐ์๋ ์ฌ์ฉ์์ ๋ก์ผ์ผ์ ๊ธฐ๋ฐ์ผ๋ก ๋ค์ํ ์ธ์ด๋ก ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด ํฌํจ๋ฉ๋๋ค. ์ ์ฒด i18n์ ๊ตฌํํ๋ ๊ฒ์ ์ด ๊ธฐ์ฌ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋์ง๋ง ๊ฐ๋ ์ ๋ณด์ฌ์ฃผ๋ ๊ฐ๋จํ ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse
from typing import Dict
app = FastAPI()
# Mock translation dictionary (replace with a real i18n library)
translations: Dict[str, Dict[str, str]] = {
"en": {
"product_not_found": "Product with ID {product_id} not found.",
"invalid_input": "Invalid input: {error_message}",
},
"fr": {
"product_not_found": "Produit avec l'ID {product_id} introuvable.",
"invalid_input": "Entrรฉe invalideย : {error_message}",
},
"es": {
"product_not_found": "Producto con ID {product_id} no encontrado.",
"invalid_input": "Entrada invรกlida: {error_message}",
},
"de": {
"product_not_found": "Produkt mit ID {product_id} nicht gefunden.",
"invalid_input": "Ungรผltige Eingabe: {error_message}",
}
}
def get_translation(locale: str, key: str, **kwargs) -> str:
"""Retrieves a translation for a given locale and key.
If the locale or key is not found, returns a default message.
"""
if locale in translations and key in translations[locale]:
return translations[locale][key].format(**kwargs)
return f"Translation missing for key '{key}' in locale '{locale}'."
@app.get("/products/{product_id}")
async def get_product(request: Request, product_id: int, locale: str = "en"):
# Simulate product lookup
if product_id > 100:
message = get_translation(locale, "product_not_found", product_id=product_id)
raise HTTPException(status_code=404, detail=message)
if product_id < 0:
message = get_translation(locale, "invalid_input", error_message="Product ID must be positive")
raise HTTPException(status_code=400, detail=message)
return {"product_id": product_id, "name": "Example Product"}
i18n ์์ ์ ๋ํ ์ฃผ์ ๊ฐ์ ์ฌํญ:
- ๋ก์ผ์ผ ๋งค๊ฐ๋ณ์: ์ด์ ๋ผ์ฐํธ๊ฐ
locale์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ฅผ ํ์ฉํ์ฌ ํด๋ผ์ด์ธํธ๊ฐ ์ ํธํ๋ ์ธ์ด๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค (๊ธฐ๋ณธ๊ฐ์ ์์ด์ ๊ฒฝ์ฐ "en"). - ๋ฒ์ญ ์ฌ์ :
translations์ฌ์ (๋ชจ์)์ ๋ค์ํ ๋ก์ผ์ผ (์ด ๊ฒฝ์ฐ ์์ด, ํ๋์ค์ด, ์คํ์ธ์ด, ๋ ์ผ์ด)์ ๋ํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ ์ฅํฉ๋๋ค. ์ค์ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ์ ์ฉ i18n ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค. get_translationํจ์: ์ด ๋์ฐ๋ฏธ ํจ์๋locale๋ฐkey์ ๋ฐ๋ผ ์ ์ ํ ๋ฒ์ญ์ ๊ฒ์ํฉ๋๋ค. ๋ํ ๋ฌธ์์ด ํ์์ ์ง์ํ์ฌ ๋์ ๊ฐ (์:product_id)์ ์ฝ์ ํฉ๋๋ค.- ๋์ ์ค๋ฅ ๋ฉ์์ง: ์ด์
HTTPException์ดget_translationํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋์ ์ผ๋ก ์์ฑ๋detail๋ฉ์์ง์ ํจ๊ป ๋ฐ์ํฉ๋๋ค.
ํด๋ผ์ด์ธํธ๊ฐ /products/101?locale=fr์ ์์ฒญํ๋ฉด ํ๋์ค์ด๋ก ์ค๋ฅ ๋ฉ์์ง๊ฐ ์์ ๋ฉ๋๋ค (๋ฒ์ญ์ด ์๋ ๊ฒฝ์ฐ). /products/-1?locale=es๋ฅผ ์์ฒญํ๋ฉด ์คํ์ธ์ด๋ก ์์ ID์ ๋ํ ์ค๋ฅ ๋ฉ์์ง๊ฐ ์์ ๋ฉ๋๋ค (๋ฒ์ญ์ด ์๋ ๊ฒฝ์ฐ).
๋ฒ์ญ์ด ์๋ ๋ก์ผ์ผ์ธ /products/200?locale=xx๋ฅผ ์์ฒญํ๋ฉด `๋ฒ์ญ ๋๋ฝ` ๋ฉ์์ง๊ฐ ํ์๋ฉ๋๋ค.
์ค๋ฅ ์ฒ๋ฆฌ ๋ชจ๋ฒ ์ฌ๋ก
FastAPI์์ ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ๊ตฌํํ ๋ ๋ช ์ฌํด์ผ ํ ๋ช ๊ฐ์ง ๋ชจ๋ฒ ์ฌ๋ก๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ์ฌ์ฉ์ ์ ์ ์์ธ ์ฌ์ฉ: ์ ํ๋ฆฌ์ผ์ด์ ์ ํน์ ์ค๋ฅ ์กฐ๊ฑด์ ๋ํ๋ด๋ ์ฌ์ฉ์ ์ ์ ์์ธ ํด๋์ค๋ฅผ ์ ์ํฉ๋๋ค.
- ์ ์ฉํ ์ค๋ฅ ๋ฉ์์ง ์ ๊ณต: ํด๋ผ์ด์ธํธ๊ฐ ์ค๋ฅ์ ์์ธ์ ์ดํดํ๋ ๋ฐ ๋์์ด ๋๋ ๋ช ํํ๊ณ ๊ฐ๊ฒฐํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํฌํจํฉ๋๋ค.
- ์ ์ ํ HTTP ์ํ ์ฝ๋ ์ฌ์ฉ: ์ค๋ฅ์ ํน์ฑ์ ์ ํํ๊ฒ ๋ฐ์ํ๋ HTTP ์ํ ์ฝ๋๋ฅผ ๋ฐํํฉ๋๋ค. ์๋ฅผ ๋ค์ด ์๋ชป๋ ์ ๋ ฅ์๋ 400 (์๋ชป๋ ์์ฒญ), ๋๋ฝ๋ ๋ฆฌ์์ค์๋ 404 (์ฐพ์ ์ ์์), ์๊ธฐ์น ์์ ์ค๋ฅ์๋ 500 (๋ด๋ถ ์๋ฒ ์ค๋ฅ)์ ์ฌ์ฉํฉ๋๋ค.
- ๋ฏผ๊ฐํ ์ ๋ณด ๋ ธ์ถ ๋ฐฉ์ง: ์ค๋ฅ ๋ฉ์์ง์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์๊ฒฉ ์ฆ๋ช ๋๋ API ํค์ ๊ฐ์ ๋ฏผ๊ฐํ ์ ๋ณด๊ฐ ๋ ธ์ถ๋์ง ์๋๋ก ์ฃผ์ํ์ญ์์ค.
- ์ค๋ฅ ๊ธฐ๋ก: ๋๋ฒ๊น
๋ฐ ๋ชจ๋ํฐ๋ง ๋ชฉ์ ์ผ๋ก ์์ธํ ์ค๋ฅ ์ ๋ณด๋ฅผ ๊ธฐ๋กํฉ๋๋ค. Python์ ๊ธฐ๋ณธ ์ ๊ณต
logging๋ชจ๋๊ณผ ๊ฐ์ ๋ก๊น ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค. - ์ค๋ฅ ์ฒ๋ฆฌ ๋ก์ง ์ค์ ์ง์คํ: ์ฌ์ฉ์ ์ ์ ์์ธ ์ฒ๋ฆฌ๊ธฐ ๋๋ ๋ฏธ๋ค์จ์ด์ ๊ฐ์ด ํ ๊ณณ์ ์ค๋ฅ ์ฒ๋ฆฌ ๋ก์ง์ ํตํฉํฉ๋๋ค.
- ์ค๋ฅ ์ฒ๋ฆฌ ํ ์คํธ: ์ค๋ฅ ์ฒ๋ฆฌ ๋ก์ง์ด ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋์ง ํ์ธํ๊ธฐ ์ํด ๋จ์ ํ ์คํธ๋ฅผ ์์ฑํฉ๋๋ค.
- ์ ์ฉ ์ค๋ฅ ์ถ์ ์๋น์ค ์ฌ์ฉ ๊ณ ๋ ค: ํ๋ก๋์ ํ๊ฒฝ์ ๊ฒฝ์ฐ Sentry ๋๋ Rollbar์ ๊ฐ์ ์ ์ฉ ์ค๋ฅ ์ถ์ ์๋น์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ค๋ฅ๋ฅผ ๋ชจ๋ํฐ๋งํ๊ณ ๋ถ์ํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ด๋ฌํ ๋๊ตฌ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ํ์ ๋ํ ๊ท์คํ ํต์ฐฐ๋ ฅ์ ์ ๊ณตํ๊ณ ๋ฌธ์ ๋ฅผ ์ ์ํ๊ฒ ์๋ณํ๊ณ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
๊ฒฐ๋ก
์ฌ์ฉ์ ์ ์ ์์ธ ์ฒ๋ฆฌ๊ธฐ๋ FastAPI์์ ๊ฐ๋ ฅํ๊ณ ์ฌ์ฉ์ ์นํ์ ์ธ API๋ฅผ ๊ตฌ์ถํ๋ ๋ฐ ์ ์ฉํ ๋๊ตฌ์ ๋๋ค. ์ฌ์ฉ์ ์ ์ ์์ธ ํด๋์ค ๋ฐ ์ฒ๋ฆฌ๊ธฐ๋ฅผ ์ ์ํ๋ฉด ์ค๋ฅ๋ฅผ ์ ์์ ์ผ๋ก ๊ด๋ฆฌํ๊ณ ํด๋ผ์ด์ธํธ์ ์ ์ฉํ ์๋ต์ ์ ๊ณตํ๋ฉฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ฐ์ ์ธ ์์ ์ฑ๊ณผ ์ ์ง ๊ด๋ฆฌ์ฑ์ ํฅ์์ํฌ ์ ์์ต๋๋ค. ์ฌ์ฉ์ ์ ์ ์์ธ, HTTPExceptions๋ฅผ ๊ฒฐํฉํ๊ณ ์ ์ฉ ๊ฐ๋ฅํ ๊ฒฝ์ฐ i18n ์์น์ ํ์ฉํ๋ฉด API๊ฐ ์ ์ธ๊ณ์ ์ผ๋ก ์ฑ๊ณตํ ์ ์์ต๋๋ค.
์ค๋ฅ ์ฒ๋ฆฌ ์ ๋ต์ ์ค๊ณํ ๋๋ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ณ ๋ คํ์ญ์์ค. ์ฌ์ฉ์๊ฐ ๋ฌธ์ ๋ฅผ ์ดํดํ๊ณ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด ๋๋ ๋ช ํํ๊ณ ๊ฐ๊ฒฐํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ ๊ณตํ์ญ์์ค. ํจ๊ณผ์ ์ธ ์ค๋ฅ ์ฒ๋ฆฌ๋ ๋ค์ํ ๊ธ๋ก๋ฒ ์ฌ์ฉ์์ ์๊ตฌ๋ฅผ ์ถฉ์กฑํ๋ ๊ณ ํ์ง API ๊ตฌ์ถ์ ์ด์์ ๋๋ค.